package com.xcity.game.equip;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import com.xcity.db.entity.Employee;
import com.xcity.game.combat.attr.CombatAttribute;
import com.xcity.game.combat.attr.CombatAttributeType;
import com.xcity.game.equip.Equip.State;
import com.xcity.game.item.ItemTemplate;

public class EquipUtils {

	public static final int MAX_LEVEL = 15;
	public static final float ATTR_GROWTH_FACTOR = 1.113264f;
	
	public static int[][] exps; // [quality][level] 升级经验需求
	
	static {
//		Logger log = EquipmentService.LOG;
		EquipQuality[] all = EquipQuality.values();
		exps = new int[all.length][];
		for (int i = 0; i < all.length; i++) {
			EquipQuality q = all[i];
			int[] expForLvls = new int[MAX_LEVEL + 1];
			for (int j = 0; j < expForLvls.length; j++) {
				if (j > 0) { // j=0: 0级
					expForLvls[j] = q.initExp + (j - 1) * q.expDeltaPerLvl + expForLvls[j - 1];
				}
//				log.info("[EQUIP EXP INIT]QUALITY[{}]LVL[{}]EXP[{}]", q, j, expForLvls[j]);
			}
			exps[i] = expForLvls;
		}
	}
	
	/**
	 * 该等级所需累计经验
	 * @param quality
	 * @param level
	 * @return
	 */
	public static int getNeedExpTotal(EquipQuality quality, int level) {
		if (level > MAX_LEVEL || level < 0) {
			return Integer.MAX_VALUE;
		}
		int[] exp = exps[quality.ordinal()];
		return exp[level];
	}
	
	/**
	 * 下一级所需经验（非累计）
	 * @param quality
	 * @param nowLvl
	 * @return
	 */
	public static int getNextLvlNeedExp(EquipQuality quality, int nowLvl) {
		int[] exp = exps[quality.ordinal()];
		if (nowLvl >= MAX_LEVEL || nowLvl < 0) {
			return exp[MAX_LEVEL] - exp[MAX_LEVEL - 1];
		}
		return exp[nowLvl + 1] - exp[nowLvl];
	}
	
	/**
	 * 根据累计经验计算所处等级
	 * @param quality
	 * @param exp
	 * @param nowLvl
	 * @return
	 */
	public static int exp2Lvl(EquipQuality quality, int exp, int nowLvl) {
		if (nowLvl < 0) {
			nowLvl = 0;
		}
		for (int lvl = nowLvl + 1; lvl <= MAX_LEVEL; lvl++) {
			int needExp = getNeedExpTotal(quality, lvl);
			if (exp - needExp < 0) {
				return lvl - 1;
			}
		}
		return MAX_LEVEL;
	}
	
	/**
	 * 根据累计经验计算在当前等级范围内的经验
	 * @param quality
	 * @param exp
	 * @param nowLvl
	 * @return
	 */
	public static int getCurrentExp(EquipQuality quality, int exp, int nowLvl) {
		nowLvl = exp2Lvl(quality, exp, nowLvl); // 修正当前等级
		if (nowLvl >= MAX_LEVEL) {
			int[] n = exps[quality.ordinal()];
			return n[MAX_LEVEL] - n[MAX_LEVEL - 1];
		}
		int needExp = getNeedExpTotal(quality, nowLvl);
		int val = exp - needExp;
		return val > 0 ? val : 0;
	}
	
	public static float calcCombatAttributeValue(List<? extends Equip> equipments, CombatAttributeType type) {
		float val = 0f;
		for (int i = 0; i < equipments.size(); i++) {
			Equip equ = equipments.get(i);
			if (!equ.isEmpty()) {
				val += equ.getAttributeValue(type);
			}
		}
		return val;
	}
	
	public static int doLevelUp(List<? extends CombatAttribute> attrs, float factor) {
		int mask = 0;
		// 主属性、物防、法防成长
		CombatAttribute attr = attrs.get(0);
		if (attr.getType() != CombatAttributeType.DEFENSE
				&& attr.getType() != CombatAttributeType.MAGIC_DEFENSE) {
			attr.setValue(attr.getValue() * factor);
			mask |= 1 << attr.getType().ordinal();
		}
		attr = find(attrs, CombatAttributeType.DEFENSE);
		if (attr != null) {
			attr.setValue(attr.getValue() * factor);
			mask |= 1 << attr.getType().ordinal();
		}
		attr = find(attrs, CombatAttributeType.MAGIC_DEFENSE);
		if (attr != null) {
			attr.setValue(attr.getValue() * factor);
			mask |= 1 << attr.getType().ordinal();
		}
		return mask;
	}
	
	public static List<CombatAttribute> getNextLevelAttrs(Equip equip) {
		if (equip.getLevel() >= MAX_LEVEL) {
			return Collections.emptyList();
		}
		List<CombatAttribute> next = new ArrayList<>(3);
		List<CombatAttribute> refers = equip.getAttrs();
		float factor = ATTR_GROWTH_FACTOR;
		// 主属性
		next.add(new com.xcity.pomelo.response.EquipmentBagResponse.CombatAttribute(refers.get(0), factor));
		// 物防、法防
		CombatAttribute attr = find(refers, CombatAttributeType.DEFENSE);
		if (attr != null) {
			next.add(new com.xcity.pomelo.response.EquipmentBagResponse.CombatAttribute(attr, factor));
		}
		attr = find(refers, CombatAttributeType.MAGIC_DEFENSE);
		if (attr != null) {
			next.add(new com.xcity.pomelo.response.EquipmentBagResponse.CombatAttribute(attr, factor));
		}
		return next;
	}
	
	public static <T extends CombatAttribute> T find(List<T> attrs, CombatAttributeType type) {
		for (int i = 0, size = attrs.size(); i < size; i++) {
			T attr = attrs.get(i);
			if (attr.getType() == type) {
				return attr;
			}
		}
		return null;
	}
	
	public static Employee getWearer(Equip equip) {
		if (equip.getState() != State.IN_EMPLOYEE) {
			return null;
		}
		long eqId = equip.getId();
		Collection<Employee> employees = equip.getVm().getOwner().getEmployees().getEmployees();
		for (Employee e : employees) {
			if (e.hasEquipment(eqId)) {
				return e;
			}
		}
		return null;
	}
	
	public static ItemTemplate toItem(Equip equip) {
		ItemTemplate item = new ItemTemplate();
		item.setId(equip.getTemplateId());
		item.setName(equip.getTemplate().getName());
		item.setIcon(equip.getTemplate().getIcon());
		item.setDesc("");
		item.setQuality((byte) equip.getQuality().ordinal());
		return item;
	}
	
}
